package com.example.ssm.service.impl;

import com.example.ssm.entity.Student;
import com.example.ssm.handler.ShitHandler;
import com.example.ssm.mapper.StudentDao;
import com.example.ssm.service.StudentService;
import com.example.ssm.service.StudentServiceStrong;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("ser1")
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Autowired
    private StudentServiceStrong studentServiceStrong;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    public Student getById(String id) {
        return studentDao.selectByPrimaryKey(id);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int updateById(Student student) {
        return studentDao.updateByPrimaryKeySelective(student);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED)
    public void testTransaction(Student student) {

        //下面这样写可以正常使用spring的事务管理
        /*StudentService myselfProxy = SpringContextUtil.getBean(StudentService.class);
        myselfProxy.updateById(student);*/

        //这样写不能使用spring的事务管理   要正常使用，必须使用的是spring的代理类，而下面的写法相当于this.updateById(student),使用的是用当前类的实例（new 出来的）。
        //updateById(student);


        //***** 1. 此处的结果会cache到mybatis一级缓存，导致 @3 处的select检索不到 @2处的更新
        Student origin = studentServiceStrong.getById(student.getId());
        System.out.println("before update:"+origin);
        ShitHandler handler = new ShitHandler();
        //***** 2. 数据库更新 如果开启了新事务，配合@1会导致@3处的select检索不到此处的更新
        int i = handler.updateSomeShitByIdWithNewBean(student);
        System.out.println("update num:" +i);
        //***** 3. 查询刚才更新的记录 ，如果在更新之前有过对本条记录的检索，就会导致此处检索不到其他事务中对本条记录的更新

        //当关闭mybatis全局缓存，且将isolation设置为 READ_COMMITTED 或者 READ_UNCOMMITTED 时，就可以避免此种情况，
        // oracle的默认隔离级别为READ_UNCOMMITTED，因此在关闭mybatis一级缓存后，oracle不存在这个问题
        Student dbRec = studentServiceStrong.getById(student.getId());
        System.out.println("after update:"+dbRec);
//        throw new RuntimeException("shit happens");
    }

}
